#include "campus_sql_connector.h"
#include "../log/campus_logger.h"

CampusSqlConnector* CampusSqlConnector::getInstance()
{
    static CampusSqlConnector instance;
    return &instance;
}

void CampusSqlConnector::setObserver(CampusSqlConnectorObserver* observer)
{
    observer_ = observer;
}

// 构造函数
CampusSqlConnector::CampusSqlConnector()
{
    try
    {
        driver = get_driver_instance();
    }
    catch (sql::SQLException &e)
    {
        CampusLogger::warn("fail to initialized databases: {}", e.what());
    }
}

// 析构函数
CampusSqlConnector::~CampusSqlConnector() { 
    stop();
}

void CampusSqlConnector::stop()
{
    running_ = false;
    cv_.notify_all();
    if(thread_ != nullptr)
    {
        thread_->join();
        delete thread_;
        thread_ = nullptr;
    }
}

int CampusSqlConnector::wait()
{
    if(thread_ && thread_->joinable())
    {
        thread_->join();
        return 0;
    }
    else{
        return 1;
    }
}

int CampusSqlConnector::run()
{
    if(running_)
    {
        CampusLogger::warn("CampusSqlConnector run fail, already running");
        return 1;
    }

    thread_ = new std::thread([this](){
        running_ = true;
        while (running_)
        {
            std::unique_lock<std::mutex> lock(mutex_);
            cv_.wait(lock, [this]() { return !sqlQueue.empty() || !running_; });
            if (!running_)
            {
                break;
            }
            auto event = sqlQueue.front();
            sqlQueue.pop();
            lock.unlock();
            
            std::vector<std::vector<std::pair<std::string, std::string>>> result;

            switch (event.type)
            {
            case INSERT:
                insert(event.sql, event.params, event.userData);
                break;
            case UPDATE:
                update(event.sql, event.params, event.userData);
                break;
            case SELECT:
                select(event.sql, event.params, result, event.userData);
                break;
            default:
                break;
            }
        }
    });

    return 0;
}

void CampusSqlConnector::exec(sqlEvent const &sqlEvent_)
{
    std::lock_guard<std::mutex>lock(mutex_);
    sqlQueue.push(sqlEvent_);
    cv_.notify_one();
}

void CampusSqlConnector::exec(std::string const &sql, sqlType type, void *userData)
{
    sqlEvent event;
    event.sql = sql;
    event.type = type;
    event.userData = userData;
    exec(event);
}

void CampusSqlConnector::exec(std::string const &sql, sqlType type, const std::vector<std::string>& params, void *userData)
{
    sqlEvent event;
    event.sql = sql;
    event.type = type;
    event.params = params;
    event.userData = userData;
    exec(event);
}

// 连接数据库
int CampusSqlConnector::init(std::string const &dbName)
{
    try
    {
        if (!driver)
        {
            driver = get_driver_instance();
        }

        con = std::unique_ptr<sql::Connection>(driver->connect("tcp://127.0.0.1:3306", "root", "liuhang20030915"));
        con->setSchema(dbName);
        con->setAutoCommit(false); // 禁用自动提交，启用事务控制
        CampusLogger::info("连接数据库{}成功",dbName);
    }
    catch (sql::SQLException &e)
    {
        CampusLogger::warn("fail to connect databases: {}", e.what());
        return 1;
    }
    return 0;
}

inline bool CampusSqlConnector::checkConnected()
{
    return con != nullptr && con->isValid();
}

// 更新数据 - 参数化查询版本
void CampusSqlConnector::update(const std::string &sqlString, const std::vector<std::string>& params, void* userData)
{
    if (!checkConnected()) {
        CampusLogger::warn("Database not connected");
        observer_->onUpdateFail(static_cast<CampusSqlInfo*>(userData));
        return;
    }

    try
    {
        std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement(sqlString));
        
        // 设置参数
        for (size_t i = 0; i < params.size(); ++i) {
            pstmt->setString(i + 1, params[i]); // 参数索引从1开始
        }
        
        pstmt->execute();
        con->commit(); // 提交事务
        CampusLogger::info("update successfully!");
        observer_->onUpdateSucess(static_cast<CampusSqlInfo*>(userData));
    }
    catch (sql::SQLException &e)
    {
        CampusLogger::warn("error while updateEvent: {}", e.what());
        if (con && !con->isClosed()) {
            con->rollback(); // 回滚事务
        }
        observer_->onUpdateFail(static_cast<CampusSqlInfo*>(userData));
    }
}

// 插入数据 - 参数化查询版本
void CampusSqlConnector::insert(const std::string &sqlString, const std::vector<std::string>& params, void* userData)
{
    if (!checkConnected()) {
        CampusLogger::warn("Database not connected");
        observer_->onInsertFail(static_cast<CampusSqlInfo*>(userData));
        return;
    }

    try
    {
        std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement(sqlString));
        
        // 设置参数
        for (size_t i = 0; i < params.size(); ++i) {
            pstmt->setString(i + 1, params[i]); // 参数索引从1开始
        }
        
        pstmt->execute();
        con->commit(); // 提交事务
        CampusLogger::info("Insert successfully!");
        observer_->onInsertSucess(static_cast<CampusSqlInfo*>(userData));
    }
    catch (sql::SQLException &e)
    {
        CampusLogger::warn("error while insertEvent: {}", e.what());
        if (con && !con->isClosed()) {
            con->rollback(); // 回滚事务
        }
        observer_->onInsertFail(static_cast<CampusSqlInfo*>(userData));
    }
}

// 查询数据 - 参数化查询版本
void CampusSqlConnector::select(const std::string &sql, const std::vector<std::string>& params, 
                         std::vector<std::vector<std::pair<std::string, std::string>>> &result, void* userData)
{
    if (!checkConnected()) {
        CampusLogger::warn("Database not connected");
        observer_->onSelectFail(static_cast<CampusSqlInfo*>(userData));
        return;
    }

    try
    {
        std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement(sql));
        
        // 设置参数
        for (size_t i = 0; i < params.size(); ++i) {
            pstmt->setString(i + 1, params[i]); // 参数索引从1开始
        }
        
        std::unique_ptr<sql::ResultSet> resultSet(pstmt->executeQuery());

        int columnCount = resultSet->getMetaData()->getColumnCount();
        while (resultSet->next())
        { // 遍历每一行
            std::vector<std::pair<std::string, std::string>> pairVector;
            for (int i = 1; i <= columnCount; ++i)
            {
                std::string columnName = resultSet->getMetaData()->getColumnName(i);
                std::string columnValue = resultSet->getString(i);

                pairVector.emplace_back(columnName, columnValue);
            }
            result.emplace_back(pairVector);
        }
        CampusLogger::info("select successfully!");
        con->commit(); // 提交事务（读取操作也需要提交以释放锁）
        
        observer_->onSelectSucess(result, static_cast<CampusSqlInfo*>(userData));
    }
    catch (sql::SQLException &e)
    {
        CampusLogger::warn("error while selectEvent: {}", e.what());
        if (con && !con->isClosed()) {
            con->rollback(); // 回滚事务
        }
        observer_->onSelectFail(static_cast<CampusSqlInfo*>(userData));
    }
}
